"use strict"

/**
 * 随机数
 * m 最小值
 * n 最大值
 * return 整数
 * 默认返回 0 / 1
 */
export const random = (m = 0, n = 1) => {
  return Math.round(Math.random() * (n - m) + m)
}

/**
 * 获取地址栏参数
 */
export const getUrlParam = (name) => {
  let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)")
  let r = window.location.search.substr(1).match(reg)
  if (r !== null) {
    return decodeURI(r[2])
  }
  return null
}

/**
 * 获取数组某个字段的平均值
 */
export const getArrayAvg = (array) => {
  var sum = 0
  for (let i = 0; i < array.length; i++) {
    const element = array[i]
    sum += Number(element.cnt)
  }
  return parseInt(sum / array.length)
}

/**
 * 对象转地址栏参数
 */
export const obj2String = (obj, arr = [], idx = 0) => {
  for (let item in obj) {
    arr[idx++] = [ item, obj[item] ]
  }
  return new URLSearchParams(arr).toString()
}

/**
 * 金额 数据 格式化  带，号的
 * source 金额
 */
export const numberComma = (source, n = 2, length = 3) => {
  source = parseFloat(source)
  source = source.toFixed(n)
  source = String(source).split(".")
  source[0] = source[0].replace(new RegExp("(\\d)(?=(\\d{" + length + "})+$)", "ig"), "$1,")
  let str = source.join(".")
  return parseInt(str) ? str : "-"
}

/**
 * 人民币金额转成汉字大写
 */
export const digitUppercase = (value) => {
  if (Number(value)) {
    let fraction = [ "角", "分" ]
    let digit = [
      "零", "壹", "贰", "叁", "肆",
      "伍", "陆", "柒", "捌", "玖"
    ]
    let unit = [
      [ "元", "万", "亿" ],
      [ "", "拾", "佰", "仟" ]
    ]
    let head = value < 0 ? "欠" : ""
    value = Math.abs(value)
    let s = ""
    for (let i = 0; i < fraction.length; i++) {
      s += (digit[Math.floor(value * 10 * Math.pow(10, i)) % 10] + fraction[i]).replace(/零./, "")
    }
    s = s || "整"
    value = Math.floor(value)
    for (let i = 0; i < unit[0].length && value > 0; i++) {
      let p = ""
      for (let j = 0; j < unit[1].length && value > 0; j++) {
        p = digit[value % 10] + unit[1][j] + p
        value = Math.floor(value / 10)
      }
      s = p.replace(/(零.)*零$/, "").replace(/^$/, "零") + unit[0][i] + s
    }
    return head + s.replace(/(零.)*零元/, "元").replace(/(零.)+/g, "零").replace(/^整$/, "零元整")
  } else {
    return "零元整"
  }
}

/**
 * 生成uuid
 * @param len 长度 number
 * @param radix 随机数基数 number
 * @returns { string }
 */
export const uuid = (len = 16, radix = 62) => {
  const chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split("")
  const uuid = []
  if (len) {
    for (let i = 0; i < len; i++) {
      uuid[i] = chars[Math.floor(Math.random() * radix)]
    }
  } else {
    let r
    uuid[8] = uuid[13] = uuid[18] = uuid[23] = "-"
    uuid[14] = "4"
    for (let i = 0; i < 36; i++) {
      if (!uuid[i]) {
        r = Math.floor(Math.random() * 16)
        uuid[i] = chars[(i === 19) ? ((r % 4) % 8) + 8 : r]
      }
    }
  }
  return uuid.join("")
}

/**
 * 随机字符串
 */
export const randomId = (n = 4) => {
  let str = ""
  for (let i = 0; i < n; i++) {
    if (str !== "") {
      str += "-" + (((1 + Math.random()) * 0x10000) | 0).toString(16)
    } else {
      str += (((1 + Math.random()) * 0x10000) | 0).toString(16)
    }
  }
  return str
}

/**
 * 时间戳转时间
 */
export const formatDate = (val, bool) => {
  if (!val) {
    return ""
  }
  let date = new Date(parseInt(val))
  let Y = date.getFullYear()
  let M = zeroFill(date.getMonth() + 1)
  let D = zeroFill(date.getDate())
  let h = zeroFill(date.getHours())
  let m = zeroFill(date.getMinutes())
  let s = zeroFill(date.getSeconds())
  let strReA = `${ Y }-${ M }-${ D } ${ h }:${ m }:${ d }`
  let strReT = `${ Y }-${ M }-${ D }`
  return bool ? strReA : strReT
}

/**
 * 判断两个对象相等
 */
export const isObjectValueEqual = (a, b) => {
  let aProps = Object.getOwnPropertyNames(a)
  let bProps = Object.getOwnPropertyNames(b)
  if (aProps.length !== bProps.length) {
    return false
  }
  for (let i = 0; i < aProps.length; i++) {
    let propName = aProps[i]
    if (a[propName] !== b[propName]) {
      return false
    }
  }
  return true
}

/**
 * @description 数组对象排序
 * @param {Array} array 数组
 * @param {String} prop 排序字段
 * @param {String} order 升序或降序, asc:升序|desc:降序
 */
export const sortData = (array, prop, order) => {
  return array.sort(function(item1, item2) {
    let value1 = item1[prop]
    let value2 = item2[prop]
    if (value1 < value2) {
      return order === "desc" ? 1 : -1
    } else if (value1 > value2) {
      return order === "desc" ? -1 : 1
    } else {
      return 0
    }
  })
}

/**
 * 防抖
 */
export const debounce = (fn, delay = 200) => {
  let timer
  return function() {
    let th = this
    let args = arguments
    if (timer) {
      clearTimeout(timer)
    }
    timer = setTimeout(function() {
      timer = null
      fn.apply(th, args)
    }, delay)
  }
}

/**
 * 节流
 */
export function throttle(fn, interval = 200) {
  let last, timer
  return function() {
    let th = this
    let args = arguments
    let now = +new Date()
    if (last && now - last < interval) {
      clearTimeout(timer)
      timer = setTimeout(function() {
        last = now
        fn.apply(th, args)
      }, interval)
    } else {
      last = now
      fn.apply(th, args)
    }
  }
}

/**
 * 获取之前日期
 * 上个月 1
 * 默认前三个月
 */
export const getMonth = (num = 3) => {
  const myTime = new Date()
  let year = myTime.getFullYear()
  let month = zeroFill(myTime.getMonth() + 1)
  let day = zeroFill(myTime.getDate())
  const now = `${ year }-${ month }-${ day }`
  if (parseInt(month) <= num) {
    const a = Math.ceil(num / 12)
    let min = num - parseInt(month) > 12 ? (num - parseInt(month)) % 12 : (num - parseInt(month))
    return {
      last: `${ year - a }-${ 12 - min }-${ day }`,
      now
    }
  }
  let preSize = new Date(year, parseInt(month) - num, 0).getDate()
  if (preSize < parseInt(day)) {
    let resultMonth = parseInt(month) - num - 1 < 10 ? ("0" + parseInt(month) - num - 1) : (parseInt(month) - 2)
    return {
      last: `${ year - isYear }-${ resultMonth }-01`,
      now
    }
  }
  return {
    last: `${ year }-${ zeroFill(month - num) }-${ day }`,
    now
  }
}

/**
 * 扁平化数组
 * @params  tree <Array> has children arguments
 */
export const getTreeMap = tree => {
  if (!(tree instanceof Array)) return
  const treeMap = []
  tree.forEach(node => {
    treeMap.push(...getNodeMap(node, tree.id))
  })
  return treeMap
}
const getNodeMap = (node, parentNode = null, leave = 0) => {
  node.parentNode = parentNode
  node.leave = leave
  const nodeMap = [ node ]
  if (node.children && node.children.length) {
    leave++
    node.children.forEach(item => nodeMap.push(...getNodeMap(item, node.value, leave)))
    // delete node.children;
  }
  return nodeMap
}

/**
 * 格式化现在的已过时间
 * @param startTime { Date }
 * @return { String }
 */
export const formatPassTime = (startTime) => {
  startTime.toString().length < 13 ? startTime = startTime * 1000 : startTime = startTime * 1
  let currentTime = Date.parse(new Date()),
    time = currentTime - startTime,
    day = parseInt(time / (1000 * 60 * 60 * 24)),
    hour = parseInt(time / (1000 * 60 * 60)),
    min = parseInt(time / (1000 * 60)),
    month = parseInt(day / 30),
    year = parseInt(month / 12)
  if (year) return year + "年前"
  if (month) return month + "个月前"
  if (day) return day + "天前"
  if (hour) return hour + "小时前"
  if (min) return min + "分钟前"
  else return "刚刚"
}

/**
 * 获取当前 日期、时间
 * @param type 类型：0 日期+时间、1 日期、2时间
 */
export const getDateTime = (type = 0) => {
  Number(type) > 2 ? type = 2 : Number(type) < 0 ? type = 0 : ""
  let date = new Date()
  let year = date.getFullYear()
  let month = date.getMonth() + 1
  let day = date.getDate()
  let hours = date.getHours()
  let minutes = date.getMinutes()
  let seconds = date.getSeconds()
  let arr = [
    `${ year }-${ zeroFill(month) }-${ zeroFill(day) } ${ hours }:${ zeroFill(minutes) }:${ zeroFill(seconds) }`,
    `${ year }-${ zeroFill(month) }-${ zeroFill(day) }`,
    `${ zeroFill(hours) }:${ zeroFill(minutes) }:${ zeroFill(seconds) }`
  ]
  return arr[type]
}

/**
 * 根据类型返回正则
 * @param str{string}: 检测的内容
 * @param type{string}: 检测类型
 */
export const checkType = (str, type) => {
  const regexp = {
    "ip": /((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}/.test(str),
    "port": /^(\d|[1-5]\d{4}|6[1-4]\d{3}|65[1-4]\d{2}|655[1-2]\d|6553[1-5])$/.test(str),
    "phone": /^1[3|4|5|6|7|8][0-9]{9}$/.test(str), //手机号
    "number": /^[0-9]+$/.test(str), //是否全数字,
    "email": /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/.test(str),
    "IDCard": /^(^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$)|(^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])((\d{4})|\d{3}[Xx])$)$/.test(str),
    "url": /[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/i.test(str)
  }
  return regexp[type]
}

/**
 * 将手机号中间部分替换为星号
 * @param phone{string}: 手机号码
 */
export const formatPhone = (phone) => {
  return phone.replace(/(\d{3})\d{4}(\d{4})/, "$1****$2")
}

export const isIos = () => {
  const u = navigator.userAgent, app = navigator.appVersion
  // 如果输出结果是true就判定是android终端或者uc浏览器
  // u.indexOf('Android') > -1 || u.indexOf('Linux') > -1;
  return (!!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/))
}

/**
 * 返回顶部
 * el 返回顶部的 Dom,  默认是 body
 */
export const backTop = (element = document.documentElement || document.body) => {
  const beginTime = Date.now()
  const beginValue = element.scrollTop
  const cubic = value => Math.pow(value, 3)
  const easeInOutCubic = value => value < 0.5
    ? cubic(value * 2) / 2
    : 1 - cubic((1 - value) * 2) / 2
  const rAF = window.requestAnimationFrame || (func => setTimeout(func, 16))
  const frameFunc = () => {
    const progress = (Date.now() - beginTime) / 500
    if (progress < 1) {
      element.scrollTop = beginValue * (1 - easeInOutCubic(progress))
      rAF(frameFunc)
    } else {
      element.scrollTop = 0
    }
  }
  rAF(frameFunc)
}

/**
 * 判断 是否在App中
 */
export const isApp = () => {
  const ua = navigator.userAgent.toLowerCase()
  if (ua.match(/MicroMessenger/i) === "micromessenger") {
    // 微信浏览器判断
    return false
  } else if (ua.match(/QQ/i) === "qq") {
    // QQ浏览器判断
    return false
  } else if (ua.match(/WeiBo/i) === "weibo") {
    return false
  } else {
    if (ua.match(/Android/i) !== null) {
      return ua.match(/browser/i) === null
    } else if (ua.match(/iPhone/i) !== null) {
      return ua.match(/safari/i) === null
    } else {
      return (ua.match(/macintosh/i) === null && ua.match(/windows/i) === null)
    }
  }
}

/**
 * 检验参数的必传
 */
export const checkParams = (checkList = [], params = {}) => {
  if (checkList.length) {
    let bol = false
    checkList.forEach(items => {
      bol = params.hasOwnProperty(items) && params[items] !== ""
      if (!bol) {
        throw new Error(`${ items } 是必传参数`)
      }
    })
    return bol
  } else {
    return true
  }
}

/**
 * 标记 console.log
 */
export const vLog = (params) => {
  console.log(
    "%c Lucky %c console %O",
    "background:#35495E; padding: 1px; border-radius: 3px 0 0 3px; color: #fff;",
    "background:#28bd6e; padding: 1px; border-radius: 0 3px 3px 0; color: #fff;margin-right: 20px",
    params
  )
}

/**
 * 数字转时长
 * number 秒
 * return 字符串 00:00:00 / 00:00
 */
export const numberToTime = (number = 0) => {
  let hours = null, minutes = null, seconds = null, only = 0, str = null
  if (number >= 3600) {
    hours = parseInt(number / 3600)
    only = number % 3600
  } else {
    hours = 0
    only = number
  }
  if (only >= 60) {
    minutes = parseInt(only / 60)
    seconds = only % 60
  } else {
    minutes = 0
    seconds = only
  }
  if (hours) {
    str = zeroFill(hours) + ":" + zeroFill(minutes) + ":" + zeroFill(seconds)
  } else {
    str = zeroFill(minutes) + ":" + zeroFill(seconds)
  }
  return str
}

/**
 * 空位补零
 * @returns 字符串
 */
export const zeroFill = (n = 0) => {
  return n < 10 ? `0${ n }` : n.toString()
}

/**
 * 数字保留小数
 * 整数不保留
 * @returns {number}
 */
export const numDecimals = (num, n = 2) => {
  // 不是数字
  if (typeof num !== "number") {
    num = Number(num) || 0
  }
  // 整数
  if (num % 1 === 0) return Number(num)
  // 小数
  return Number(num.toFixed(n))
}

/**
 * 获取文件后缀
 * @param filename {string}
 * @returns {string}
 */
export const getFileExt = (filename = "") => {
  if (typeof filename == "string") {
    return filename.split(".").pop().toLowerCase()
  } else {
    throw new Error("filename must be a string type")
  }
}

/**
 * 是否是小数
 */
export const isFloat = (n) => parseInt(n) < parseFloat(n)

/**
 * 数字大小
 */
export const strNumSize = (tempNum) => {
  let stringNum = tempNum.toString()
  let index = stringNum.indexOf(".")
  let newNum = stringNum
  if (index !== -1) {
    newNum = stringNum.substring(0, index)
  }
  return newNum.length
}

/**
 * 数字转换
 * @param num
 * @returns {{unit: string, num: (string|number)}}
 */
export const unitConvert = (num = 0) => {
  let moneyUnits = [ "", "万", "亿", "万亿" ]
  let dividend = 10000
  let curentNum = num
  // 转换数字
  let curentUnit = moneyUnits[0]
  // 转换单位
  for (let i = 0; i < 4; i++) {
    curentUnit = moneyUnits[i]
    if (strNumSize(curentNum) < 5) {
      break
    }
    curentNum = curentNum / dividend
  }
  return {
    num: isFloat(curentNum) ? curentNum.toFixed(2) : curentNum,
    unit: curentUnit
  }
}
